# 33. 符号运算

33

const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
});

class Fraction {
    constructor(fenzi, fenmu) {
        if (fenmu === 0) {
            throw new Error('ERROR');
        }
        let gcd = this.gcd(Math.abs(fenzi), Math.abs(fenmu));
        this.fenzi = fenzi/gcd;
        this.fenmu = fenmu/gcd;
        if (this.fenmu < 0) {
            this.fenzi = -this.fenzi;
            this.fenmu = -this.fenmu;
        }
    }

    add(other) {
        return new Fraction(this.fenzi*other.fenmu+other.fenzi*this.fenmu, this.fenmu*other.fenmu);
    }

    subtract(other) {
        return new Fraction(this.fenzi*other.fenmu-other.fenzi*this.fenmu, this.fenmu*other.fenmu);
    }

    multiply(other) {
        return new Fraction(this.fenzi*other.fenzi, this.fenmu*other.fenmu);
    }

    divide(other) {
        return new Fraction(this.fenzi*other.fenmu, this.fenmu*other.fenzi);
    }
}

gcd(a,b) {
    return b===0 ? a : this.gcd(b, a%b)
}

toString() {
    if(this.fenzi === 1) {
        return String(this.fenzi);
    } else {
        return this.fenzi + '/' + this.fenmu;
    }
}

function calc(expression) {
    let numbers = [];
    let op = [];
    for(let i=0; i<expression.length; i++) {
        let c = expression[i];
        if(!isNaN(c)) {
            let j=i;
            while(j<expression.length && !isNaN(expression[j])) {
                j++;
            }
            let number = new Fraction(parseInt(expresssion.substring(i,j)), 1);
            numbers.push(number);
            i=j-1;
        } else if(c==='(') {
            op.push(c);
        } else if(c===')') {
            while(op[op-1] !== '(') {
                preformCalc(numbers, op);
            }
            op.pop();
        } else if(c=='+' || c=='-' || c=='*' || c=='/') {
            while(op.length>0 && precedence(c) <= precedence(op[op.length-1]) ) {
                preformCalc(numbers, op);
            }
            op.push(c);
        }
    }

    while(op.length > 0) {
        preformCalc(numbers, op);
    }
    return numbers.pop();
}

function performCalc(numbers, op) {
    let b = numbers.pop();
    let a = numbers.pop();
    let opx = op.pop();
    switch(opx) {
        case '+':
            numbers.push(a.add(b));
            break;
        case '-':
            numbers.push(a.subtract(b));
            break;
        case '*':
            numbers.push(a.multiply(b));
            break;
        case '/':
            numbers.push(a.divide(b));
            break;
    }
}

function precedence(op) {
    switch(op) {
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
        default:
            return 0;
    }
}

rl.on('line', (line) => {
    try {
        let res = calc(line);
        console.log(res.toString());
    } catch(e) {
        console.log('ERROR');
    }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124